Sensor Fusion for Kinetis MCUs (ISSDK/KSDK version)
main_freertos_agm02_power_cycling.c File Reference
+ Include dependency graph for main_freertos_agm02_power_cycling.c:

Go to the source code of this file.

Functions

void vApplicationIdleHook (void)
 
void vApplicationTickHook (void)
 
static void read_task (void *pvParameters)
 
static void fusion_task (void *pvParameters)
 
bool motionCheck (float sample[3], float baseline[3], float tolerance, uint32_t winLength, uint32_t *count)
 
int main (void)
 

Variables

SensorFusionGlobals sfg
 
ControlSubsystem controlSubsystem
 
StatusSubsystem statusSubsystem
 
PhysicalSensor sensors [3]
 
EventGroupHandle_t event_group = NULL
 

Detailed Description

This file shows one recommended way to incorporate sensor fusion capabilities into a FreeRTOS project AND adds intelligent power down of sensors when the DUT is stationary.

Definition in file main_freertos_agm02_power_cycling.c.

Function Documentation

static void fusion_task ( void *  pvParameters)
static

Definition at line 135 of file main_freertos_agm02_power_cycling.c.

Referenced by main(), and vApplicationTickHook().

136 {
137  uint16_t i=0; // general counter variable
138  float motion_baseline[3] = {0.0, 0.0, 0.0};
139  bool stationary;
140  static bool lastStationary;
141  uint32_t stationaryCount = 0;
142  while (1)
143  {
144  xEventGroupWaitBits(event_group, /* The event group handle. */
145  B0, /* The bit pattern the event group is waiting for. */
146  pdTRUE, /* BIT_0 and BIT_4 will be cleared automatically. */
147  pdFALSE, /* Don't wait for both bits, either bit unblock task. */
148  portMAX_DELAY); /* Block indefinitely to wait for the condition to be met. */
149 
150  // sfg.runFusion(&sfg); // Run the actual fusion algorithms
151  // Rather than call runFusion directly, this example invokes the lower level
152  // calls here. This allows us to check to see if the board is stationary,
153  // and if so, transition to a lower power state.
154  sfg.conditionSensorReadings(&sfg); // magCal is run as part of this
155  stationary = motionCheck(
156  sfg.Accel.fGc, // calibrated accelerometer reading
157  motion_baseline, // baseline to check new values against
158  0.01, // changes less than this are ignored
159  120, // three seconds at 40Hz rate
160  &stationaryCount);
161  if (stationary) {
162  if (!lastStationary) { // suspend some operations
163  FXAS21002_Idle(&(sensors[1]), &sfg);
164  MAG3110_Idle(&(sensors[2]), &sfg);
165  }
166  sfg.clearFIFOs(&sfg);
167  } else {
168  if (lastStationary) { // restart operations
169  FXAS21002_Init(&(sensors[1]), &sfg);
170  MAG3110_Init(&(sensors[2]), &sfg);
171  }
172  // fuse the sensor data
173  sfg.runFusion(&sfg);
174  }
175 
176  sfg.applyPerturbation(&sfg); // apply debug perturbation (testing only)
177 
178  sfg.loopcounter++; // The loop counter is used to "serialize" mag cal operations
179  i=i+1;
180  if (i>=4) { // Some status codes include a "blink" feature. This loop
181  i=0; // should cycle at least four times for that to operate correctly.
182  sfg.updateStatus(&sfg); // This is where pending status updates are made visible
183  }
184  if (stationary) {
185  sfg.queueStatus(&sfg, LOWPOWER); // assume LOWPOWER status for next pass through the loop
186  } else {
187  sfg.queueStatus(&sfg, NORMAL); // assume NORMAL status for next pass through the loop
188  }
189  sfg.pControlSubsystem->stream(&sfg, sUARTOutputBuffer); // Send stream data to the Sensor Fusion Toolbox
190  lastStationary = stationary;
191  }
192 }
int32_t loopcounter
counter incrementing each iteration of sensor fusion (typically 25Hz)
clearFIFOs_t * clearFIFOs
clear sensor FIFOs
conditionSensorReadings_t * conditionSensorReadings
preprocessing step for sensor fusion
bool motionCheck(float sample[3], float baseline[3], float tolerance, uint32_t winLength, uint32_t *count)
The motionCheck() function is not a sensor fusion function. It is a function that simply monitors an ...
Definition: motionCheck.c:44
streamData_t * stream
function to create packets for serial stream
Definition: control.h:73
EventGroupHandle_t event_group
SensorFusionGlobals sfg
This is the primary sensor fusion data structure.
struct ControlSubsystem * pControlSubsystem
#define B0
Definition: sensor_fusion.h:88
PhysicalSensor sensors[3]
This implementation uses three physical sensors.
updateStatus_t * updateStatus
status=next status
Running in reduced power mode.
uint8_t sUARTOutputBuffer[256]
main output buffer defined in control.c
Definition: control.c:59
runFusion_t * runFusion
run the fusion routines
int8_t FXAS21002_Idle(PhysicalSensor *sensor, SensorFusionGlobals *sfg)
int8_t MAG3110_Init(PhysicalSensor *sensor, SensorFusionGlobals *sfg)
setStatus_t * queueStatus
queue status change for next regular interval
int8_t MAG3110_Idle(PhysicalSensor *sensor, SensorFusionGlobals *sfg)
applyPerturbation_t * applyPerturbation
apply step function for testing purposes
int8_t FXAS21002_Init(PhysicalSensor *sensor, SensorFusionGlobals *sfg)
Operation is Nominal.

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

int main ( void  )

This is a FreeRTOS (dual task) implementation of the NXP sensor fusion demo build.

Definition at line 90 of file main_freertos_agm02_power_cycling.c.

91 {
92  ARM_DRIVER_I2C* I2Cdrv = &I2C_S_DRIVER_BLOCKING; // defined in the <shield>.h file
93  BOARD_InitPins(); // defined in pin_mux.c, initializes pkg pins
94  BOARD_BootClockRUN(); // defined in clock_config.c, initializes clocks
95  BOARD_InitDebugConsole(); // defined in board.c, initializes the OpenSDA port
96 
97  I2Cdrv->Initialize(NULL); // Initialize the KSDK driver for the I2C port
98  I2Cdrv->Control(ARM_I2C_BUS_SPEED, ARM_I2C_BUS_SPEED_FAST); // Configure the I2C bus speed
99 
100  initializeControlPort(&controlSubsystem); // configure pins and ports for the control sub-system
101  initializeStatusSubsystem(&statusSubsystem); // configure pins and ports for the status sub-system
102  initSensorFusionGlobals(&sfg, &statusSubsystem, &controlSubsystem); // Initialize sensor fusion structures
103  // "install" the sensors we will be using
104  sfg.installSensor(&sfg, &sensors[0], FXLS8952C_I2C_ADDR, 1, (void*) I2Cdrv, FXLS8952_Init, FXLS8952_Read);
105  sfg.installSensor(&sfg, &sensors[1], FXAS21002_I2C_ADDR, 1, (void*) I2Cdrv, FXAS21002_Init, FXAS21002_Read);
106  sfg.installSensor(&sfg, &sensors[2], MAG3110_I2C_ADDR, 1, (void*) I2Cdrv, MAG3110_Init, MAG3110_Read);
107  sfg.initializeFusionEngine(&sfg); // This will initialize sensors and magnetic calibration
108 
109  event_group = xEventGroupCreate();
110  xTaskCreate(read_task, "READ", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 2, NULL);
111  xTaskCreate(fusion_task, "FUSION", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, NULL);
112 
113  sfg.setStatus(&sfg, NORMAL); // If we got this far, let's set status state to NORMAL
114  vTaskStartScheduler(); // Start the RTOS scheduler
115  sfg.setStatus(&sfg, HARD_FAULT); // If we got this far, FreeRTOS does not have enough memory allocated
116  for (;;) ;
117 }
void initSensorFusionGlobals(SensorFusionGlobals *sfg, StatusSubsystem *pStatusSubsystem, ControlSubsystem *pControlSubsystem)
utility function to insert default values in the top level structure
Definition: sensor_fusion.c:68
int8_t FXLS8952_Read(PhysicalSensor *sensor, SensorFusionGlobals *sfg)
void initializeStatusSubsystem(StatusSubsystem *pStatus)
initializeStatusSubsystem() should be called once at startup to initialize the data structure and to ...
Definition: status.c:185
EventGroupHandle_t event_group
installSensor_t * installSensor
function for installing a new sensor into t
SensorFusionGlobals sfg
This is the primary sensor fusion data structure.
initializeFusionEngine_t * initializeFusionEngine
set sensor fusion structures to initial values
PhysicalSensor sensors[3]
This implementation uses three physical sensors.
int8_t FXAS21002_Read(PhysicalSensor *sensor, SensorFusionGlobals *sfg)
int8_t MAG3110_Read(PhysicalSensor *sensor, SensorFusionGlobals *sfg)
static void fusion_task(void *pvParameters)
ControlSubsystem controlSubsystem
used for serial communications
int8_t initializeControlPort(ControlSubsystem *pComm)
Initialize the control subsystem and all related hardware.
Definition: control.c:182
int8_t FXLS8952_Init(PhysicalSensor *sensor, SensorFusionGlobals *sfg)
ARM_DRIVER_I2C * I2Cdrv
KSDK handle for the I2C port defined in Driver_I2C_KSDK2.c.
Non-recoverable FAULT = something went very wrong.
int8_t MAG3110_Init(PhysicalSensor *sensor, SensorFusionGlobals *sfg)
setStatus_t * setStatus
change status indicator immediately
static void read_task(void *pvParameters)
int8_t FXAS21002_Init(PhysicalSensor *sensor, SensorFusionGlobals *sfg)
Operation is Nominal.
StatusSubsystem statusSubsystem
provides visual (usually LED) status indicator

+ Here is the call graph for this function:

bool motionCheck ( float  sample[3],
float  baseline[3],
float  tolerance,
uint32_t  winLength,
uint32_t *  count 
)

The motionCheck() function is not a sensor fusion function. It is a function that simply monitors an accelerometer or magnetometer tri-axial sensor output, returning Boolean true if the sensor appears to be stationary, and false otherwise. This function would normally be called from your fusion_tasks in your main().

Parameters
sampleprocessed triaxial sensor sample (accel or mag)
baselineprevious value to compare to
tolerancehow much tolerance you can stand
winLengthhow many samples need to be stable to assert "noMotion"
counthow many samples so far we've been not moving

Definition at line 44 of file motionCheck.c.

Referenced by fusion_task(), and vApplicationTickHook().

51 {
52  float change[3];
53  bool changed;
54  change[CHX] = fabs(baseline[CHX] - sample[CHX]);
55  change[CHY] = fabs(baseline[CHY] - sample[CHY]);
56  change[CHZ] = fabs(baseline[CHZ] - sample[CHZ]);
57  changed = (change[CHX]>tolerance) ||
58  (change[CHY]>tolerance) ||
59  (change[CHZ]>tolerance);
60  if (changed) {
61  baseline[CHX] = sample[CHX];
62  baseline[CHY] = sample[CHY];
63  baseline[CHZ] = sample[CHZ];
64  *count = 0;
65  } else {
66  if ((*count) <= winLength) (*count) += 1;
67  }
68  return(*count > winLength);
69 }
#define CHY
Used to access Y-channel entries in various data data structures.
Definition: sensor_fusion.h:77
#define CHZ
#define CHX
Used to access X-channel entries in various data data structures.
Definition: sensor_fusion.h:76

+ Here is the caller graph for this function:

static void read_task ( void *  pvParameters)
static

Definition at line 119 of file main_freertos_agm02_power_cycling.c.

Referenced by main(), and vApplicationTickHook().

120 {
121  uint16_t i=0; // general counter variable
122  portTickType lastWakeTime;
123  const portTickType frequency = 1; // tick counter runs at the read rate
124  lastWakeTime = xTaskGetTickCount();
125  while (1)
126  {
127  for (i=1; i<=OVERSAMPLE_RATE; i++) {
128  vTaskDelayUntil(&lastWakeTime, frequency);
129  sfg.readSensors(&sfg, i); // Reads sensors, applies HAL and does averaging (if applicable)
130  }
131  xEventGroupSetBits(event_group, B0);
132  }
133 }
#define OVERSAMPLE_RATE
EventGroupHandle_t event_group
SensorFusionGlobals sfg
This is the primary sensor fusion data structure.
readSensors_t * readSensors
read all physical sensors
#define B0
Definition: sensor_fusion.h:88

+ Here is the caller graph for this function:

void vApplicationIdleHook ( void  )

Definition at line 69 of file main_freertos_agm02_power_cycling.c.

70 {
71  // MCU low power modes are not debugged at this point in time
72  //volatile smc_power_state_t state;
73  //SMC_SetPowerModeStop(SMC, kSMC_PartialStop );
74  //state = SMC_GetPowerModeState(SMC);
75  //asm("wfi");
76 }
void vApplicationTickHook ( void  )

Definition at line 77 of file main_freertos_agm02_power_cycling.c.

78 {
79  sfg.queueStatus(&sfg, NORMAL); // assume NORMAL status for next pass through the loop
80 }
SensorFusionGlobals sfg
This is the primary sensor fusion data structure.
setStatus_t * queueStatus
queue status change for next regular interval
Operation is Nominal.

+ Here is the call graph for this function:

Variable Documentation

ControlSubsystem controlSubsystem

used for serial communications

Definition at line 65 of file main_freertos_agm02_power_cycling.c.

EventGroupHandle_t event_group = NULL

Definition at line 68 of file main_freertos_agm02_power_cycling.c.

Referenced by fusion_task(), main(), and read_task().

PhysicalSensor sensors[3]

This implementation uses three physical sensors.

Definition at line 67 of file main_freertos_agm02_power_cycling.c.

This is the primary sensor fusion data structure.

Definition at line 64 of file main_freertos_agm02_power_cycling.c.

StatusSubsystem statusSubsystem

provides visual (usually LED) status indicator

Definition at line 66 of file main_freertos_agm02_power_cycling.c.